package com.ssy.lingxi.report.serviceimpl.tally;

import com.ssy.lingxi.report.api.enums.AccountOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.CreditOperateTypeEnum;
import com.ssy.lingxi.report.api.enums.OperateDataSourceEnum;
import com.ssy.lingxi.report.api.vo.request.OperateNoticeVO;
import com.ssy.lingxi.report.dao.pay.AssetAccountDAO;
import com.ssy.lingxi.report.dao.pay.CreditDAO;
import com.ssy.lingxi.report.entity.report.MemberTallyReportDO;
import com.ssy.lingxi.report.model.bo.MemberTallyReportBO;
import com.ssy.lingxi.report.model.bo.StatisticsCountBO;
import com.ssy.lingxi.report.model.bo.tally.AsetAccountTallyBO;
import com.ssy.lingxi.report.model.bo.tally.CreditTallyBO;
import com.ssy.lingxi.report.model.bo.tally.statistics.CreditStatisticsTallyBO;
import com.ssy.lingxi.report.model.constant.pay.TradeStatusEnum;
import com.ssy.lingxi.report.model.vo.response.AccountTallyReportVO;
import com.ssy.lingxi.report.model.vo.response.TallyReportItemVO;
import com.ssy.lingxi.report.service.tally.IAccountTallyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 账号中心计数统计接口实现
 * @author 伍将
 * @date 2020/11/23
 * @version 2.0.0
 */
@Service
public class AccountTallyServiceImpl implements IAccountTallyService {

    private static final Logger logger = LoggerFactory.getLogger(AccountTallyServiceImpl.class);

    @Autowired
    private CreditDAO creditDAO;
    @Autowired
    private AssetAccountDAO accountDAO;

    /**
     * 资金账户
     * @param tallyReportO
     * @param noticeVO
     * @return
     */
    @Override
    public MemberTallyReportBO setAccount(MemberTallyReportBO tallyReportO, OperateNoticeVO noticeVO) {

        OperateDataSourceEnum sourceEnum = OperateDataSourceEnum.getEnum(noticeVO.getDataSource());
        switch (sourceEnum) {
            case CREDIT: // 授信
                tallyReportO.setCredit(setCreditTally(tallyReportO, noticeVO));
                break;
            case ACCOUNT: // 资金账户
                tallyReportO.setAsetAccount(setAsetAccountTally(tallyReportO, noticeVO));
                break;
        }
        return tallyReportO;
    }

    /**
     * 转换资金账户
     * @param reportBO
     * @return
     */
    @Override
    public AccountTallyReportVO convertAccount(MemberTallyReportBO reportBO) {
        AccountTallyReportVO result = new AccountTallyReportVO();
        if (reportBO == null) {
            reportBO = new MemberTallyReportBO();
        }
        // 转换资金账户
        result.setAccountList(convertAsetAccountTally(reportBO.getAsetAccount()));
        // 转换授信
        result.setCreditList(convertCreditTally(reportBO.getCredit()));

        return result;
    }

    /**
     * 转换授信
     * @param tallyBO
     * @return
     */
    private List<TallyReportItemVO> convertCreditTally(CreditTallyBO tallyBO) {
        List<TallyReportItemVO> resultList = new ArrayList<>();
        if (tallyBO == null) {
            tallyBO = new CreditTallyBO();
        }

        // 待提交审核
        TallyReportItemVO tallyReportItem = new TallyReportItemVO();
        tallyReportItem.setCount(tallyBO.getToBeCommitValifyCount());
        tallyReportItem.setName(CreditOperateTypeEnum.TO_BE_VALIFY_COMMIT.getName());
        tallyReportItem.setLink(CreditOperateTypeEnum.TO_BE_VALIFY_COMMIT.getLink());
        resultList.add(tallyReportItem);
        // 待一级审核
        tallyReportItem = new TallyReportItemVO();
        tallyReportItem.setCount(tallyBO.getToBeValifyStep1Count());
        tallyReportItem.setName(CreditOperateTypeEnum.TO_BE_VALIFY_STEP1.getName());
        tallyReportItem.setLink(CreditOperateTypeEnum.TO_BE_VALIFY_STEP1.getLink());
        resultList.add(tallyReportItem);
        // 待二级审核
        tallyReportItem = new TallyReportItemVO();
        tallyReportItem.setCount(tallyBO.getToBeValifyStep2Count());
        tallyReportItem.setName(CreditOperateTypeEnum.TO_BE_VALIFY_STEP2.getName());
        tallyReportItem.setLink(CreditOperateTypeEnum.TO_BE_VALIFY_STEP2.getLink());
        resultList.add(tallyReportItem);
        // 待三级审核
        tallyReportItem = new TallyReportItemVO();
        tallyReportItem.setCount(tallyBO.getToBeValifyStep3Count());
        tallyReportItem.setName(CreditOperateTypeEnum.TO_BE_VALIFY_STEP3.getName());
        tallyReportItem.setLink(CreditOperateTypeEnum.TO_BE_VALIFY_STEP3.getLink());
        resultList.add(tallyReportItem);
        // 待确认审核结果
        tallyReportItem = new TallyReportItemVO();
        tallyReportItem.setCount(tallyBO.getToBeConfirmCount());
        tallyReportItem.setName(CreditOperateTypeEnum.TO_BE_CONFIRM.getName());
        tallyReportItem.setLink(CreditOperateTypeEnum.TO_BE_CONFIRM.getLink());
        resultList.add(tallyReportItem);

        resultList.forEach(o -> o.setCount(o.getCount() > 0 ? o.getCount() : 0));

        return resultList;
    }

    /**
     * 转换账户
     * @param tallyBO
     * @return
     */
    private List<TallyReportItemVO> convertAsetAccountTally(AsetAccountTallyBO tallyBO) {
        List<TallyReportItemVO> resultList = new ArrayList<>();
        if (tallyBO == null) {
            tallyBO = new AsetAccountTallyBO();
        }

        // 待提交审核
        TallyReportItemVO tallyReportItem = new TallyReportItemVO();
        tallyReportItem.setCount(tallyBO.getTobeValifyCashoutCount());
        tallyReportItem.setName(AccountOperateTypeEnum.TO_BE_VALIFY_CASHOUT.getName());
        tallyReportItem.setLink(AccountOperateTypeEnum.TO_BE_VALIFY_CASHOUT.getLink());
        resultList.add(tallyReportItem);
        // 待一级审核
        tallyReportItem = new TallyReportItemVO();
        tallyReportItem.setCount(tallyBO.getTobePayCashoutCount());
        tallyReportItem.setName(AccountOperateTypeEnum.TO_BE_PAY_CASHOUT.getName());
        tallyReportItem.setLink(AccountOperateTypeEnum.TO_BE_PAY_CASHOUT.getLink());
        resultList.add(tallyReportItem);

        resultList.forEach(o -> o.setCount(o.getCount() > 0 ? o.getCount() : 0));

        return resultList;
    }

    /**
     * 设置授信
     * @param tallyReportO
     * @param noticeVO
     * @return
     */
    private CreditTallyBO setCreditTally(MemberTallyReportBO tallyReportO, OperateNoticeVO noticeVO) {
        if (tallyReportO == null) {
            tallyReportO = new MemberTallyReportBO();
        }
        CreditTallyBO creditTallyBO = tallyReportO.getCredit();
        if (creditTallyBO == null) {
            creditTallyBO = new CreditTallyBO();
        }
        // 更新数据
        CreditOperateTypeEnum typeEnum;
        if (noticeVO.getReduceCount() > 0) {
            typeEnum = CreditOperateTypeEnum.getEnum(noticeVO.getReduceOperateType());
            if (typeEnum != null) {
                switch (typeEnum) {
                    case TO_BE_VALIFY_COMMIT:
                        creditTallyBO.setToBeCommitValifyCount(creditTallyBO.getToBeCommitValifyCount() - noticeVO.getReduceCount());
                        break;
                    case TO_BE_VALIFY_STEP1:
                        creditTallyBO.setToBeValifyStep1Count(creditTallyBO.getToBeValifyStep1Count() - noticeVO.getReduceCount());
                        break;
                    case TO_BE_VALIFY_STEP2:
                        creditTallyBO.setToBeValifyStep2Count(creditTallyBO.getToBeValifyStep2Count() - noticeVO.getReduceCount());
                        break;
                    case TO_BE_VALIFY_STEP3:
                        creditTallyBO.setToBeValifyStep3Count(creditTallyBO.getToBeValifyStep3Count() - noticeVO.getReduceCount());
                        break;
                    case TO_BE_CONFIRM:
                        creditTallyBO.setToBeConfirmCount(creditTallyBO.getToBeConfirmCount() - noticeVO.getReduceCount());
                        break;
                }
            }
        }
        if (noticeVO.getIncreaseCount() > 0) {
            typeEnum = CreditOperateTypeEnum.getEnum(noticeVO.getIncreaseOperateType());
            if (typeEnum != null) {
                switch (typeEnum) {
                    case TO_BE_VALIFY_COMMIT:
                        creditTallyBO.setToBeCommitValifyCount(creditTallyBO.getToBeCommitValifyCount() + noticeVO.getIncreaseCount());
                        break;
                    case TO_BE_VALIFY_STEP1:
                        creditTallyBO.setToBeValifyStep1Count(creditTallyBO.getToBeValifyStep1Count() + noticeVO.getIncreaseCount());
                        break;
                    case TO_BE_VALIFY_STEP2:
                        creditTallyBO.setToBeValifyStep2Count(creditTallyBO.getToBeValifyStep2Count() + noticeVO.getIncreaseCount());
                        break;
                    case TO_BE_VALIFY_STEP3:
                        creditTallyBO.setToBeValifyStep3Count(creditTallyBO.getToBeValifyStep3Count() + noticeVO.getIncreaseCount());
                        break;
                    case TO_BE_CONFIRM:
                        creditTallyBO.setToBeConfirmCount(creditTallyBO.getToBeConfirmCount() + noticeVO.getIncreaseCount());
                        break;
                }
            }
        }

        return creditTallyBO;
    }

    /**
     * 设置账户
     * @param tallyReportO
     * @param noticeVO
     * @return
     */
    private AsetAccountTallyBO setAsetAccountTally(MemberTallyReportBO tallyReportO, OperateNoticeVO noticeVO) {
        if (tallyReportO == null) {
            tallyReportO = new MemberTallyReportBO();
        }
        AsetAccountTallyBO asetAccountBO = tallyReportO.getAsetAccount();
        if (asetAccountBO == null) {
            asetAccountBO = new AsetAccountTallyBO();
        }
        // 更新数据
        AccountOperateTypeEnum typeEnum;
        if (noticeVO.getReduceCount() > 0) {
            typeEnum = AccountOperateTypeEnum.getEnum(noticeVO.getReduceOperateType());
            if (typeEnum != null) {
                switch (typeEnum) {
                    case TO_BE_VALIFY_CASHOUT:
                        asetAccountBO.setTobeValifyCashoutCount(asetAccountBO.getTobeValifyCashoutCount() - noticeVO.getReduceCount());
                        break;
                    case TO_BE_PAY_CASHOUT:
                        asetAccountBO.setTobePayCashoutCount(asetAccountBO.getTobePayCashoutCount() - noticeVO.getReduceCount());
                        break;
                }
            }
        }
        if (noticeVO.getIncreaseCount() > 0) {
            typeEnum = AccountOperateTypeEnum.getEnum(noticeVO.getIncreaseOperateType());
            if (typeEnum != null) {
                switch (typeEnum) {
                    case TO_BE_VALIFY_CASHOUT:
                        asetAccountBO.setTobeValifyCashoutCount(asetAccountBO.getTobeValifyCashoutCount() + noticeVO.getIncreaseCount());
                        break;
                    case TO_BE_PAY_CASHOUT:
                        asetAccountBO.setTobePayCashoutCount(asetAccountBO.getTobePayCashoutCount() + noticeVO.getIncreaseCount());
                        break;
                }
            }
        }

        return asetAccountBO;
    }


    /**
     * 统计计数
     * @param reportList
     * @return
     */
    @Override
    public List<MemberTallyReportDO> statisticsTally(List<MemberTallyReportDO> reportList) {

        // 统计授信
        reportList = statisticsCreditTally(reportList);

        // 统计资金账户
        reportList = statisticsAsetAccountTally(reportList);

        return reportList;
    }

    /**
     * 统计账户
     * @param reportList
     * @return
     */
    private List<MemberTallyReportDO> statisticsAsetAccountTally(List<MemberTallyReportDO> reportList) {
        if (reportList == null) {
            reportList = new ArrayList<>();
        }
        List<StatisticsCountBO> statisticsList = accountDAO.getAssetAccountStatisticsCount();
        if (statisticsList == null) {
            logger.info("没有符合条件的账户计数统计数据");
            statisticsList = new ArrayList<>();
        }

        // 补全统计数据
        List<MemberTallyReportDO> finalReportList = reportList;
        statisticsList.stream().distinct().forEach(p -> {
            MemberTallyReportDO reportDO = finalReportList.stream()
                    .filter(o -> o.getMemberId().equals(p.getMemberId()) && o.getRoleId().equals(p.getRoleId()))
                    .findFirst().orElse(null);
            if (reportDO == null) {
                reportDO = new MemberTallyReportDO();
                reportDO.setMemberId(p.getMemberId());
                reportDO.setRoleId(p.getRoleId());
                finalReportList.add(reportDO);
            }
        });

        List<StatisticsCountBO> finalStatisticsList = statisticsList;
        finalReportList.forEach(p -> {
            // 如果报表数据为null，则实例化
            if (p.getTallyReport() == null) {
                p.setTallyReport(new MemberTallyReportBO());
            }
            AsetAccountTallyBO tallyBO = new AsetAccountTallyBO();
            // 待审核提现
            tallyBO.setTobeValifyCashoutCount(finalStatisticsList.stream()
                    .filter(o -> o.getMemberId().equals(p.getMemberId()) && o.getRoleId().equals(p.getRoleId())
                            && o.getStatusType().equals(TradeStatusEnum.ApplyCashOut.getCode()))
                    .mapToLong(StatisticsCountBO::getCount).sum());
            // 待支付提现
            tallyBO.setTobePayCashoutCount(finalStatisticsList.stream()
                    .filter(o -> o.getMemberId().equals(p.getMemberId()) && o.getRoleId().equals(p.getRoleId())
                            && o.getStatusType().equals(TradeStatusEnum.CheckPass.getCode()))
                    .mapToLong(StatisticsCountBO::getCount).sum());
            p.getTallyReport().setAsetAccount(tallyBO);
        });

        return finalReportList;
    }

    /**
     * 统计授信
     * @param reportList
     * @return
     */
    private List<MemberTallyReportDO> statisticsCreditTally(List<MemberTallyReportDO> reportList) {
        if (reportList == null) {
            reportList = new ArrayList<>();
        }
        List<CreditStatisticsTallyBO> tallyVOList = creditDAO.getCreditApplyStatisticsCount();
        List<StatisticsCountBO> statisticsList = tallyVOList.stream().map(r -> {
            StatisticsCountBO statisticsCountBO = new StatisticsCountBO();
            statisticsCountBO.setMemberId(r.getMemberId());
            statisticsCountBO.setRoleId(r.getRoleId());
            return statisticsCountBO;
        }).collect(Collectors.toList());

        // 补全统计数据
        List<MemberTallyReportDO> finalReportList = reportList;
        statisticsList.stream().distinct().forEach(p -> {
            MemberTallyReportDO reportDO = finalReportList.stream()
                    .filter(o -> o.getMemberId().equals(p.getMemberId()) && o.getRoleId().equals(p.getRoleId()))
                    .findFirst().orElse(null);
            if (reportDO == null) {
                reportDO = new MemberTallyReportDO();
                reportDO.setMemberId(p.getMemberId());
                reportDO.setRoleId(p.getRoleId());
                finalReportList.add(reportDO);
            }
        });

        finalReportList.forEach(p -> {
            // 如果报表数据为null，则实例化
            if (p.getTallyReport() == null) {
                p.setTallyReport(new MemberTallyReportBO());
            }
            CreditTallyBO creditBO = new CreditTallyBO();
            CreditStatisticsTallyBO tallyVO = tallyVOList.stream().filter(o -> o.getMemberId().equals(p.getMemberId()) && o.getRoleId().equals(p.getRoleId())).findFirst().orElse(null);
            if (null != tallyVO) {
                // 待提交审核
                creditBO.setToBeCommitValifyCount(tallyVO.getToBeCommitValifyCount());
                // 待一级审核
                creditBO.setToBeValifyStep1Count(tallyVO.getToBeValifyStep1Count());
                // 待二级审核
                creditBO.setToBeValifyStep2Count(tallyVO.getToBeValifyStep2Count());
                // 待三级审核
                creditBO.setToBeValifyStep3Count(tallyVO.getToBeValifyStep3Count());
                // 待确认审核
                creditBO.setToBeConfirmCount(tallyVO.getToBeConfirmCount());
            }
            p.getTallyReport().setCredit(creditBO);
        });

        return finalReportList;
    }
}
